﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace HobSoft.SoccerBet2014.Domain.Implementation
{
    using Common.Errors;
    using Core;
    using Models.Core;

    public class SampleDataService : ISampleDataService
    {
        protected readonly ConcurrentDictionary<Type, IRepository> repositoryContainer = new ConcurrentDictionary<Type, IRepository>();

        protected virtual void RegisterRepository(Type type, IRepository repository)
        {
            type.IsNull().ThrowNull("type");
            repository.IsNull().ThrowNull("repository");

            repositoryContainer.TryAdd(type, repository);
        }

        protected virtual IReadonlyRepository<T> GetReadRepository<T>() where T : class, IModel
        {
            Type type = typeof(T);
            if (!repositoryContainer.ContainsKey(type))
                Error.ThrowNotSupported("服务不支持对该数据的读取访问");
            var repository = repositoryContainer[type] as IReadonlyRepository<T>;
            repository.IsNull().ThrowNotSupported("服务不支持对该数据的读取访问");
            return repository;
        }

        protected virtual IReadWriteRepository<T> GetWriteRepository<T>() where T : class, IModel
        {
            Type type = typeof(T);
            if (!repositoryContainer.ContainsKey(type))
                Error.ThrowNotSupported("服务不支持对该数据的读写访问");
            var repository = repositoryContainer[type] as IReadWriteRepository<T>;
            repository.IsNull().ThrowNotSupported("服务不支持对该数据的读写访问");
            return repository;
        }

        public IList<T> GetAll<T>() where T : class, IModel
        {
            return GetReadRepository<T>().GetMany(m => true);
        }

        public IList<T> GetMany<T>(Expression<Func<T, bool>> predicate) where T : class, IModel
        {
            return GetReadRepository<T>().GetMany(predicate);
        }

        public IList<T> GetMany<T>(params object[] keys) where T : class, IModel
        {
            var repository= GetReadRepository<T>();
            var ukeyRepository = repository as IUniKeyReadRepository<T>;
            ukeyRepository.IsNull().ThrowNotSupported("不支持非单键的数据方法");
            return ukeyRepository.GetMany(keys);
        }

        public T Get<T>(object key) where T : class, IModel
        {
            return GetReadRepository<T>().Get(key);
        }

        public T Get<T>(Expression<Func<T, bool>> predicate) where T : class, IModel
        {
            return GetReadRepository<T>().Get(predicate);
        }

        public T AddOrUpdate<T>(T model) where T : class, IModel
        {
            return GetWriteRepository<T>().AddOrUpdate(model);
        }

        public int AddOrUpdate<T>(IList<T> models) where T : class, IModel
        {
            return GetWriteRepository<T>().AddOrUpdate(models);
        }

        public bool Delete<T>(T model) where T : class, IModel
        {
            return GetWriteRepository<T>().Delete(model);
        }

        public bool Delete<T>(object key) where T : class, IModel
        {
            var repository = GetWriteRepository<T>();
            var ukeyRepository = repository as IUniKeyWriteRepository<T>;
            ukeyRepository.IsNull().ThrowNotSupported("不支持非单键的数据方法");
            return ukeyRepository.DeleteMany(key) > 0;
        }

        public int DeleteMany<T>(Expression<Func<T, bool>> predicate) where T : class, IModel
        {
            return GetWriteRepository<T>().DeleteMany(predicate);
        }
    }
}
